package org.canaan.spring.resolver;

import com.alibaba.fastjson.JSON;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;

public class JsonParamArgumentResolver implements HandlerMethodArgumentResolver {
    private final Logger logger = LoggerFactory.getLogger(JsonParamArgumentResolver.class);

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        //对要解析的参数进行判断，是否需要此解析器
        return parameter.hasParameterAnnotation(JsonParam.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        Class<?> clazz = parameter.getParameterType();
        String paramName = parameter.getParameterName();
        String paramValue = webRequest.getParameter(paramName);

        JsonParam requestParam = parameter.getParameterAnnotation(JsonParam.class);

        if (StringUtils.isBlank(paramValue)) {
            if (requestParam.required()) {
                throw new MethodArgumentConversionNotSupportedException(paramValue, JsonParam.class, paramName, parameter, new IllegalArgumentException("参数不为空"));
            }
            return null;
        }

        try {
            if (List.class.isAssignableFrom(clazz)) {    //是一个集合
                Class<?> listItemClass = null;
                Type supperType = parameter.getNestedGenericParameterType();
                if (supperType instanceof ParameterizedType) {
                    //获取泛型的类型
                    Type[] paramTypes = ((ParameterizedType) supperType).getActualTypeArguments();
                    if (paramTypes.length > 0) {
                        listItemClass = (Class<?>) paramTypes[0];
                    }
                }
                if (listItemClass == null) {
                    List<String> list = JSON.parseArray(paramValue, String.class);
                    return CollectionUtils.removeAll(list, Collections.singleton(null));
                }
                return CollectionUtils.removeAll(JSON.parseArray(paramValue, listItemClass), Collections.singleton(null));
            }
            return JSON.parseObject(paramValue, clazz);
        } catch (Exception e) {
            logger.error("json参数解析失败 key:{} value:{}", paramName, paramValue, e);
            throw new MethodArgumentConversionNotSupportedException(paramValue, JsonParam.class, paramName, parameter, new IllegalArgumentException("参数异常"));
        }
    }

}
